package com.cipher;


import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class AesExample {

    public static void main(String[] args) throws Exception {
        String plainText = "Hello, World! Hello, World! ";
        String key = "1234567890123456"; // 16 bytes for AES-128

        String iv = "abcdefghabcdefgh";

        // ECB Mode
        String ecbCipherText = encryptECB(plainText, key);
        String ecbDecryptedText = decryptECB(ecbCipherText, key);
        System.out.println("ECB 加密: " + ecbCipherText);
        System.out.println("ECB 解密: " + ecbDecryptedText);

        // CBC Mode
        String cbcCipherText = encryptCBC(plainText, key,iv);
        String cbcDecryptedText = decryptCBC(cbcCipherText, key,iv);
        System.out.println("CBC 加密: " + cbcCipherText);
        System.out.println("CBC 解密: " + cbcDecryptedText);

        // CFB Mode
        String cfbCipherText = encryptCFB(plainText, key,iv);
        String cfbDecryptedText = decryptCFB(cfbCipherText, key,iv);
        System.out.println("CFB 加密: " + cfbCipherText);
        System.out.println("CFB 解密: " + cfbDecryptedText);

        // OFB Mode
        String ofbCipherText = encryptOFB(plainText, key,iv);
        String ofbDecryptedText = decryptOFB(ofbCipherText, key,iv);
        System.out.println("OFB 加密: " + ofbCipherText);
        System.out.println("OFB 解密: " + ofbDecryptedText);

        // CTR Mode
        String ctrCipherText = encryptCTR(plainText, key,iv);
        String ctrDecryptedText = decryptCTR(ctrCipherText, key,iv);
        System.out.println("CTR 加密: " + ctrCipherText);
        System.out.println("CTR 解密: " + ctrDecryptedText);
    }

    // ECB Mode
    public static String encryptECB(String plainText, String key) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        return Base64.getEncoder().encodeToString(cipher.doFinal(plainText.getBytes()));
    }

    public static String decryptECB(String cipherText, String key) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)));
    }

    // CBC Mode
    public static String encryptCBC(String plainText, String key,String iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv.getBytes()));
        return Base64.getEncoder().encodeToString(cipher.doFinal(plainText.getBytes()));
    }

    public static String decryptCBC(String cipherText, String key,String iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv.getBytes()));
        return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)));
    }

    // CFB Mode
    public static String encryptCFB(String plainText, String key,String iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CFB/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv.getBytes()));
        return Base64.getEncoder().encodeToString(cipher.doFinal(plainText.getBytes()));
    }

    public static String decryptCFB(String cipherText, String key,String iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CFB/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv.getBytes()));
        return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)));
    }

    // OFB Mode
    public static String encryptOFB(String plainText, String key,String iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/OFB/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv.getBytes()));
        return Base64.getEncoder().encodeToString(cipher.doFinal(plainText.getBytes()));
    }

    public static String decryptOFB(String cipherText, String key,String iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/OFB/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv.getBytes()));
        return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)));
    }

    // CTR Mode
    public static String encryptCTR(String plainText, String key,String iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv.getBytes()));
        return Base64.getEncoder().encodeToString(cipher.doFinal(plainText.getBytes()));
    }

    public static String decryptCTR(String cipherText, String key,String iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv.getBytes()));
        return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)));
    }
}